#!/usr/bin/env python
#
# syslog_setup.py
#
# Version : 0.7
# Date : 20080520
#
# Author : Bernard Czenkusz
# Email  : bernie@skipole.co.uk

# syslog_setup.py - Displays syslog setup panel and is a module in sm_gui
# package, run as part of the skipolemonitor gui interface
#
# Copyright (c) 2007 Bernard Czenkusz
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

""" This is a module in the sm_gui package, and defines the Syslog setup panel

It is run as part of the skipolemonitor gui interface.
"""


import wx
import logging
import sm_syslog
import socket

from net import *


# --------- The SyslogSetup Panel which is used by one of the tabs, in the SetupNotebook Window

class SyslogSetup(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        #
        # Create the syslog sizer, splitting the Panel vertically
        self.syslog_sizer=wx.BoxSizer(wx.VERTICAL)
        #
        # Create the input fields and text in a grid sizer
        self.fields_sizer=wx.FlexGridSizer(rows=0, cols=2, hgap=20, vgap=20)
        button_size = (100,40)
        #
        # Group syslog messages enable
        self.group_syslog_enable_field = wx.CheckBox(self, -1, "")
        self.fields_sizer.Add(self.group_syslog_enable_field, 0, wx.ALIGN_RIGHT)
        if net_cfg["GROUP_SYSLOG_ENABLED"]=="0":
            self.group_syslog_enable_field.SetValue(0)
        else:
            self.group_syslog_enable_field.SetValue(1)
        group_syslog_enable_text=wx.StaticText(self, -1, "Send Syslog messages when Groups change status")
        self.fields_sizer.Add(group_syslog_enable_text, 0, wx.ALIGN_LEFT)
        #
        # Host syslog messages enable
        self.host_syslog_enable_field = wx.CheckBox(self, -1, "")
        self.fields_sizer.Add(self.host_syslog_enable_field, 0, wx.ALIGN_RIGHT)
        if net_cfg["HOST_SYSLOG_ENABLED"]=="0":
            self.host_syslog_enable_field.SetValue(0)
        else:
            self.host_syslog_enable_field.SetValue(1)
        host_syslog_enable_text=wx.StaticText(self, -1, "Send Syslog messages when Hosts change status")
        self.fields_sizer.Add(host_syslog_enable_text, 0, wx.ALIGN_LEFT)
        #
        # Syslog server
        self.syslog_server_field = wx.TextCtrl(self, -1, net_cfg["SYSLOG_SERVER"], size=(200,-1))
        self.syslog_server_field.SetToolTipString("Syslog server")
        self.fields_sizer.Add(self.syslog_server_field, 0, wx.ALIGN_RIGHT)
        syslog_server_text=wx.StaticText(self, -1, "The syslog server which will receive syslog messages")
        self.fields_sizer.Add(syslog_server_text, 0, wx.ALIGN_LEFT)
        #
        # Make column 1 growable - this allows the right descriptions to be large
        self.fields_sizer.AddGrowableCol(1,0)
        #
        # Add grid fields_sizer to the main sizer
        self.syslog_sizer.Add(self.fields_sizer, 0, wx.ALL | wx.ALIGN_CENTER, 40)
        #
        # -- Apply - Cancel - Test -- buttons
        #
        # Create a horizontal button_sizer to hold the buttons
        self.button_sizer=wx.BoxSizer(wx.HORIZONTAL)
        #
        # Apply button
        self.apply_button = wx.Button(self, wx.ID_APPLY, size=button_size)
        self.apply_button.Enable(False)
        self.apply_button.SetToolTipString("Click to apply changes.")
        self.button_sizer.Add(self.apply_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        # Cancel button
        self.cancel_button = wx.Button(self, wx.ID_CANCEL, size=button_size)
        self.cancel_button.Enable(False)
        self.cancel_button.SetToolTipString("Click to cancel changes.")
        self.button_sizer.Add(self.cancel_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        # Test button
        self.test_button = wx.Button(self, label="&Test", size=button_size)
        self.test_button.SetToolTipString("Click to send test message.")
        self.button_sizer.Add(self.test_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        if net_cfg["HOST_SYSLOG_ENABLED"]=="0" and net_cfg["GROUP_SYSLOG_ENABLED"]=="0":
            self.test_button.Enable(False)
        #
        #
        # Add button_sizer to the main sizer
        self.syslog_sizer.Add(self.button_sizer, 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER, 40)
        #
        # Create test results box
        if net_cfg["HOST_SYSLOG_ENABLED"]=="0" and net_cfg["GROUP_SYSLOG_ENABLED"]=="0":
            results_text="Syslog messages are disabled, until one or both of the above checkboxes are ticked - and the Apply button pressed."
        else:
            results_text="On pressing Test, a syslog message will be sent"
        self.results_box=wx.StaticText(self, -1, results_text, size=(400,50), style=wx.ST_NO_AUTORESIZE)
        self.results_box.SetBackgroundColour('White')
        #
        # Add the results_box to the main sizer
        self.syslog_sizer.Add(self.results_box, 0, wx.ALL | wx.ALIGN_CENTER, 40)
        #
        # Set the size to the panel
        self.SetSizer(self.syslog_sizer)
        #
        # Bind the fields
        self.Bind(wx.EVT_CHECKBOX, self.group_syslog_enable, self.group_syslog_enable_field)
        self.Bind(wx.EVT_CHECKBOX, self.host_syslog_enable, self.host_syslog_enable_field)
        self.Bind(wx.EVT_TEXT, self.syslog_server, self.syslog_server_field)
        #
        # Bind the buttons
        self.Bind(wx.EVT_BUTTON, self.apply_button_pressed, self.apply_button)
        self.Bind(wx.EVT_BUTTON, self.cancel_button_pressed, self.cancel_button)
        self.Bind(wx.EVT_BUTTON, self.test_button_pressed, self.test_button)

    # Syslog field binding methods, - enable Apply and Cancel buttons,
    # Disable Test button, and check input length

    def group_syslog_enable(self, event):
        """group syslog enable checkbox toggled"""
        self.apply_button.Enable(True)
        self.cancel_button.Enable(True)
        self.test_button.Enable(False)
        return

    def host_syslog_enable(self, event):
        """host syslog enable checkbox toggled"""
        self.apply_button.Enable(True)
        self.cancel_button.Enable(True)
        self.test_button.Enable(False)
        return

    def syslog_server(self, event):
        """Limit syslog server address to 50 characters"""
        self.apply_button.Enable(True)
        self.cancel_button.Enable(True)
        self.test_button.Enable(False)
        text = event.GetString()
        if len(text)>50:
            pos=self.syslog_server_field.GetInsertionPoint()
            self.syslog_server_field.Remove(50,len(text)+1)
            self.syslog_server_field.SetInsertionPoint(pos)

    # Button binding methods

    def apply_button_pressed(self, event):
        """ Apply button - check and apply all fields"""
        #
        # Enable Group Syslog messages
        if self.group_syslog_enable_field.GetValue():
            net_cfg["GROUP_SYSLOG_ENABLED"]="1"
        else:
            net_cfg["GROUP_SYSLOG_ENABLED"]="0"
        #
        # Enable Host Syslog messages
        if self.host_syslog_enable_field.GetValue():
            net_cfg["HOST_SYSLOG_ENABLED"]="1"
        else:
            net_cfg["HOST_SYSLOG_ENABLED"]="0"
        #
        # Syslog Server
        text=self.syslog_server_field.GetValue()
        text=str(text).strip()
        if validate.check_part_address(text):
            # So the name is formatted correctly
            net_cfg["SYSLOG_SERVER"]=text
            # Check server name resolves correctly
            try:
                socket.gethostbyname(text)
            except:
                wx.MessageBox("The syslog server name cannot be resolved",
                               caption="ERROR",
                               style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
        else:
            wx.MessageBox("The syslog server is formatted incorrectly",
                           caption="ERROR",
                           style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
            self.syslog_server_field.SetValue(net_cfg["SYSLOG_SERVER"])
        #
        # Save config file to disc
        if not writeconfigtofile():
            wx.MessageBox("ERROR: Unable to save changes to disk",
                           caption="ERROR",
                           style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
        # Only enable the test button if the checkboxes are enabled
        if net_cfg["HOST_SYSLOG_ENABLED"]=="0" and net_cfg["GROUP_SYSLOG_ENABLED"]=="0":
            self.test_button.Enable(False)
            self.results_box.SetLabel("Syslog messages are disabled, until one or both of the above checkboxes are ticked - and the Apply button pressed.")
        else:
            self.test_button.Enable(True)
            self.results_box.SetLabel("On pressing Test, a syslog message will be sent")
        #
        # As Apply has been pressed, disable the Apply and Cancel buttons
        self.apply_button.Enable(False)
        self.cancel_button.Enable(False)
        #
        # Stop the logger
        #
        sm_syslog.stop_logger()
        #
        # Re-start the logger - which will pick up the new net_cfg values
        #
        if not sm_syslog.create_logger():
            self.results_box.SetLabel("Error : Syslog failure, syslog messages have not been enabled")
            net_cfg["HOST_SYSLOG_ENABLED"]="0"
            net_cfg["GROUP_SYSLOG_ENABLED"]="0"
            self.host_syslog_enable_field.SetValue(0)
            self.group_syslog_enable_field.SetValue(0)
            self.test_button.Enable(False)
            

    def cancel_button_pressed(self, event):
        """ Cancel button - return syslog fields to original values"""
        #
        if net_cfg["GROUP_SYSLOG_ENABLED"]=="0":
            self.group_syslog_enable_field.SetValue(0)
        else:
            self.group_syslog_enable_field.SetValue(1)
        #
        if net_cfg["HOST_SYSLOG_ENABLED"]=="0":
            self.host_syslog_enable_field.SetValue(0)
        else:
            self.host_syslog_enable_field.SetValue(1)
        #
        # Syslog Server
        self.syslog_server_field.SetValue(net_cfg["SYSLOG_SERVER"])
        #
        # Only enable the test button if the checkboxes are enabled
        if net_cfg["HOST_SYSLOG_ENABLED"]=="0" and net_cfg["GROUP_SYSLOG_ENABLED"]=="0":
            self.test_button.Enable(False)
            self.results_box.SetLabel("Syslog messages are disabled, until one or both of the above checkboxes are ticked - and the Apply button pressed.")
        else:
            self.test_button.Enable(True)
            self.results_box.SetLabel("On pressing Test, a syslog message will be sent")
        self.apply_button.Enable(False)
        self.cancel_button.Enable(False)

    def test_button_pressed(self, event):
        """Test button - send a syslog message and report any errors"""
        # Create the syslog
        self.results_box.SetLabel("Sending syslog message to: "+net_cfg["SYSLOG_SERVER"] + "\nPlease wait...")
        try:
            socket.gethostbyname(net_cfg["SYSLOG_SERVER"])
        except:
            self.results_box.SetLabel("Message not sent, syslog server name cannot be resolved")
            return
        # wait one second then call self.send_test_message
        wx.FutureCall(1000, self.send_test_message)

    def send_test_message(self):
        """Sends a test syslog message, and puts results into self.results_box"""
        if sm_syslog.LOGGER_RUNNING == 0:
            self.results_box.SetLabel("Message not sent, due to a local failure")
            return
        self.results_box.SetLabel("Message sent: You should check to see if the message was received.")
        try:
            logging.warning("Skipole Monitor : Test Message")
        except:
            self.results_box.SetLabel("Error : no information available")
        return


